#pragma once
using namespace System;

#define UNMANAGEDPOINTER_DECLARATION()\
	virtual property IntPtr UnmanagedPointer { IntPtr get(){return IntPtr(_This);}}

#define REGISTEREDOBJECT_DECLARATION()\
	virtual property bool IsRegistered { bool get(){return DRegisteredObjects::Get(IntPtr(_This)) != nullptr;}}

#define X86
//#define X64

#if defined(X86)
	typedef int GeomKey;
#elif defined(X64)
	typedef __int64 GeomKey;
#endif

namespace Skill
{
	namespace Ode
	{
		public interface class DIUnmanagedPointer
		{
			property IntPtr UnmanagedPointer
			{
				IntPtr get();
			}			
		};

		///<summary>
		/// All of this types must dispose manually or remove from DRegisteredObjects
		///</summary>
		public interface class DIRegisteredObject : DIUnmanagedPointer
		{
		
			property bool IsRegistered
			{
				bool get();
			}

			property String^ Name
			{
				String^ get();
				void set(String^ value);
			}
		};


		public ref class DRegisteredObjects abstract sealed
		{
		public:

			static GeomKey GetKey(IntPtr k)		
			{
#if defined(X86)
				return k.ToInt32();
#elif defined(X64)
				return k.ToInt64();
#endif
			}
		internal:

			static System::Collections::Generic::Dictionary<GeomKey,DIRegisteredObject^>^ objects;
		public:

			static DRegisteredObjects()
			{
				objects = gcnew System::Collections::Generic::Dictionary<GeomKey,DIRegisteredObject^>();
			}

			static void Add(DIRegisteredObject^ p)
			{
				GeomKey key = GetKey(p->UnmanagedPointer);
				if(objects->ContainsKey(key))
					return;
				objects->Add(key,p);
			}
			static DIRegisteredObject^ Get(IntPtr key)
			{
				DIRegisteredObject^ p;
				objects->TryGetValue(GetKey(key),p);
				return p;
			}
			static void Remove(DIRegisteredObject^ p)
			{
				objects->Remove(GetKey(p->UnmanagedPointer));
			}
			static property int RegisteredObjectsCount
			{
				int get(){return objects->Count; }
			}
		};
	}
}